package ei

import (
	"reflect"
	"strconv"
)

type typeClass int

const (
	TYPE_SPC    typeClass = 0
	TYPE_FLOAT  typeClass = 1
	TYPE_STRING typeClass = 3
	TYPE_SYMBOL typeClass = 5
	TYPE_TXT    typeClass = 6
	TYPE_ARGS   typeClass = 7 // 函数的参数
	TYPE_EXPR   typeClass = 8
	TYPE_FUNC   typeClass = 9
	TYPE_LIST   typeClass = 10
	TYPE_TAGET  typeClass = 11 // （自变量）
	TYPE_INDEX	typeClass = 12 // 在[]中的内容，表示数组序号
	TYPE_STRUCT	typeClass = 13 // 结构体，底层通过map实现
	TYPE_FIELD	typeClass = 14 // 结构体的字段名（防止在计算时作为变量寻值
	TYPE_PTR	typeClass = 15 // 指针，便于=赋值操作
)

func FromBestMatch(v interface{}) Token {
	switch v.(type) {
	case float64:
		return FromFloat64(v.(float64))
	case float32:
		return FromFloat32(v.(float32))
	case int:
		return FromInt(v.(int))
	default:
		panic("无法找到最佳匹配类型")
	}
}

func GetFloat64(t Token) float64 {
	switch t.TypeClass {
	case TYPE_FLOAT:
		return t.Value.(float64)
	case TYPE_STRING:
		v, err := strconv.ParseFloat(t.Value.(string), 64)
		if checkErr(err) {
			panic(err)
		} else {
			return v
		}
	case TYPE_PTR:
		return GetFloat64(GetPtrValue(t))
	}
	panic("无法解析" + t.Str() + "为float64")
}
func FromFloat64(f float64) Token {
	return Token{
		TypeClass: TYPE_FLOAT,
		Value:     f,
	}
}

func GetFloat32(t Token) float32 {
	switch t.TypeClass {
	case TYPE_FLOAT:
		return float32(t.Value.(float64))
	case TYPE_STRING:
		v, err := strconv.ParseFloat(t.Value.(string), 32)
		if checkErr(err) {
			return float32(v)
		} else {
			panic("转换失败")
		}
	case TYPE_PTR:
		return GetFloat32(GetPtrValue(t))
	default:
		panic("不能转换的类型")
	}
}
func FromFloat32(f float32) Token {
	return Token{
		TypeClass: TYPE_FLOAT,
		Value:     float64(f),
	}
}

func Getint(t Token) int {
	switch t.TypeClass {
	case TYPE_FLOAT:
		v := int(t.Value.(float64))
		if float64(v) != t.Value.(float64) {
			println("警告：将浮点数转换为整数")
		}
		return v
	case TYPE_STRING:
		v, err := strconv.Atoi(t.Value.(string))
		if checkErr(err) {
			return v
		} else {
			panic("转换失败")
		}
	case TYPE_PTR:
		return Getint(GetPtrValue(t))
	default:
		v, ok := t.Value.(int)
		if ok {
			return v
		} else {
			panic("不能转换类型为int")
		}
	}
}

func FromInt(i int) Token {
	return Token{
		TypeClass: TYPE_FLOAT,
		Value:     float64(i),
	}
}

func GetString(t Token) string {
	return t.ValueStr()
}

func FromString(v string) Token {
	return Token{
		TypeClass: TYPE_STRING,
		Value:     v,
	}
}

func FromStruct(v interface{}) Token {
	t := reflect.TypeOf(v)
	value := reflect.ValueOf(v)
	var m = make(map[string]Token)
	for i := 0; i < t.NumField(); i++ {
		m[t.Field(i).Name] = FromBestMatch(value.Field(i).Interface())
	}
	return Token{
		TypeClass: TYPE_STRUCT,
		Value:     m,
	}
}

func GetStruct(v Token, dest interface{}) bool {
	if v.TypeClass == TYPE_PTR {
		return GetStruct(GetPtrValue(v), dest)
	}
	value := reflect.ValueOf(dest).Elem()
	if reflect.ValueOf(dest).Kind() != reflect.Ptr || value.Kind() != reflect.Struct {
		print("GetStruct的dest参数需要指针类型的结构体")
	}
	m := GetMap(v)
	for key, val := range m{
		if !value.FieldByName(key).CanSet(){
			panic("无法设置结构体字段")
		}
		switch value.FieldByName(key).Kind() {
		case reflect.Float64:
			value.FieldByName(key).SetFloat(GetFloat64(val))
		case reflect.Float32:
			value.FieldByName(key).SetFloat(GetFloat64(val))
			println("不支持设置32位浮点，按64位处理")
		case reflect.Int:
			value.FieldByName(key).SetInt(int64(Getint(val)))
		default:
			panic("暂不支持字段" + key + "映射为结构体")
		}
	}
	return true
}

func FromMap(v map[string]Token) Token {
	return Token{
		TypeClass: TYPE_STRUCT,
		Value:     v,
	}
}

func GetMap(v Token) map[string]Token {
	if v.TypeClass == TYPE_PTR {
		return GetMap(GetPtrValue(v))
	}
	if v.TypeClass == TYPE_STRUCT {
		return v.Value.(map[string]Token)
	} else {
		return nil
	}
}

func AsGroup(t []Token) Token {
	if len(t) == 1 && t[0].TypeClass == TYPE_ARGS {
		return t[0]
	} else {
		return Token{
			TypeClass: TYPE_ARGS,
			Value:     t,
		}
	}
}

func ParseArgs(Arg Token, r ...interface{}) {
	if Arg.TypeClass != TYPE_ARGS && Arg.TypeClass != TYPE_LIST {
		panic("输入的Arg 不是参数类型(Group)")
	}
	if len(Arg.Value.([]Token)) != len(r) {
		switch r[len(r)-1].(type) {
		case *[]Token:
		default:
			panic("输入参数和输出参数的个数不匹配")
		}

	}
	arg := Arg.Value.([]Token)
	for i := 0; i < len(r); i++ {
		switch r[i].(type) {
		case *float64:
			*r[i].(*float64) = GetFloat64(arg[i])
		case *[]float64:
			for i := 0; i < len(arg); i++ {
				*r[i].(*[]float64) = append(*r[i].(*[]float64), arg[i].ToFloat64())
			}
		case *float32:
			*r[i].(*float32) = GetFloat32(arg[i])
		case *[]float32:
			for i := 0; i < len(arg); i++ {
				*r[i].(*[]float32) = append(*r[i].(*[]float32), arg[i].ToFloat32())
			}
		case *int:
			*r[i].(*int) = Getint(arg[i])
		case *string:
			*r[i].(*string) = arg[i].ValueStr()
		case *Token:
			*r[i].(*Token) = arg[i]
		case *[]Token:
			*r[i].(*[]Token) = arg[i:]
		case *Expr:
			if arg[i].TypeClass == TYPE_EXPR {
				*r[i].(*Expr) = arg[i].Value.(Expr)
			} else {
				panic("不是Expr类型" + arg[i].Str())
			}

		default:
			panic("不支持解析参数[" + strconv.Itoa(i) + "]的类型，" + arg[i].Str())
		}
	}
}

func ParseExprArgs(ip *Interpreter,Arg ...Expr) Token {
	r := make([]Token, len(Arg))
	for i := 0; i < len(Arg); i++ {
		r[i] = Arg[i].Cal(ip, true)
	}
	return Token{
		TypeClass: TYPE_LIST,
		Value:     r,
	}
}

func SpcToken() Token {
	return Token{
		TypeClass: TYPE_SPC,
		Value:     nil,
	}
}
